#ifndef CS488_VIEWER_HPP
#define CS488_VIEWER_HPP

#include <gtkmm.h>
#include <gtkglmm.h>
#include "algebra.hpp"
#include "game.hpp"

// The "main" OpenGL widget
class Viewer : public Gtk::GL::DrawingArea {
public:
  Viewer();
  virtual ~Viewer();
    enum myColor{
        FIREBRICK,
        GREY,
        BLACK,
        BROWN,
        BLUE,
        GREEN,
        RED,
        PURPLE,
        YELLOW,
        ORANGE
    };
    enum mySpeed{
        SLOW = 700,
        MEDIUM = 500,
        FAST = 300
    };
    
    enum myDrawMode{
        WIREFRAME,
        FACE,
        MULTICOLOURED,
    };
    
  // A useful function that forces this widget to rerender. If you
  // want to render a new frame, do not call on_expose_event
  // directly. Instead call this, which will cause an on_expose_event
  // call when the time is right.
  void invalidate();
    void moveLeft();
	void moveRight();
	void rotateCW();
	void rotateCCW();
    void drop();
    void pause();
    void set_scale_mode(bool m);
    void set_draw_mode(myDrawMode m);
    void set_speed(mySpeed s);
    void set_double_buffer();
    void set_bevel();
    void set_light();
    void reset();
    void restart();
protected:

  // Events we implement
  // Note that we could use gtkmm's "signals and slots" mechanism
  // instead, but for many classes there's a convenient member
  // function one just needs to define that'll be called with the
  // event.

  // Called when GL is first initialized
  virtual void on_realize();
  // Called when our window needs to be redrawn
  virtual bool on_expose_event(GdkEventExpose* event);
  // Called when the window is resized
  virtual bool on_configure_event(GdkEventConfigure* event);
  // Called when a mouse button is pressed
  virtual bool on_button_press_event(GdkEventButton* event);
  // Called when a mouse button is released
  virtual bool on_button_release_event(GdkEventButton* event);
  // Called when the mouse moves
  virtual bool on_motion_notify_event(GdkEventMotion* event);

private:
    void initialize();
    void drawGameWell();
    void drawCube(int part);
    void topFace();
	void frontFace();
	void rightFace();
	void leftFace();
	void bottomFace();
	void backFace();
    void set_color(myColor c);
    bool start();
    void drawFallingPieces();
    void setup_lighting();
    bool spin();
    void drawNumber(int num, int colorindex);
    bool loseAnimate();
    
    Game myGame;
    bool m_lose;
    bool button1;
    bool button2;
    bool button3;
    int alpha, theta, gammar;
    Point2D init_point;
    bool scale_mode;
	double m_scale;
    myDrawMode draw_mode;
    double speed;
    double current_speed;
    bool double_buffer;
    sigc::connection connection, spin_connection, lose_connection;
    double spin_velocity;
    bool spin_release_button1, spin_release_button2, spin_release_button3;
    int score;
    int accum;
    bool m_bevel;
    bool m_light;
    int animate_lose_counter;
    bool m_pause;
};

#endif
